/*
按照不同类型与目录分开执行操作。例如：
压缩文件、直接复制文件、编译ES6与样式文件等。
*/

const { src, dest, parallel, series, watch } = require('gulp');
const plugins = require('gulp-load-plugins')()
const browserSync = require('browser-sync').create()
const del = require('del')

//来自课程提前准备的数据？
const data = {
    menus: [
        {
            name: 'Home',
            icon: 'aperture',
            link: 'index.html'
        },
        {
            name: 'Features',
            link: 'features.html'
        },
        {
            name: 'About',
            link: 'about.html'
        },
        {
            name: 'Contact',
            link: '#',
            children: [
                {
                    name: 'Twitter',
                    link: 'https://twitter.com/w_zce'
                },
                {
                    name: 'About',
                    link: 'https://weibo.com/zceme'
                },
                {
                    name: 'divider'
                },
                {
                    name: 'About',
                    link: 'https://github.com/zce'
                }
            ]
        }
    ],
    pkg: require('./package.json'),
    date: new Date()
}

//通过指定src的base，使src与dist的其后的结构统一。类似html中的base path。
//样式编译
const convertCss = () => {
    return src('src/assets/styles/*.scss', {
        base: 'src'
    })
        .pipe(plugins.sass({
            //这样会让每个style的大括号换到下一行。这里还有nested等值。
            outputStyle: 'expanded'
        }))
        .pipe(dest('temp'))
}
//脚本编译
//babel只是个平台，需要preset来指定特性（来转换）
const convertJs = () => {
    return src('src/assets/scripts/*.js', { base: 'src' })
        .pipe(plugins.babel({
            presets: ['@babel/preset-env']
        }))
        .pipe(dest('temp'))
}
//页面模板编译
const convertHtml = () => {
    return src('src/**/*.html', { base: 'src' })
        .pipe(plugins.swig({ data }))
        .pipe(dest('temp'))
}
//图片和字体文件转换
const convertImage = () => {
    return src('src/assets/images/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
const convertFont = () => {
    return src('src/assets/fonts/**', { base: 'src' })
        .pipe(plugins.imagemin())
        .pipe(dest('dist'))
}
//其他文件及文件清除
const convertExtra = () => {
    return src('public/**', { base: 'public' })
        .pipe(dest('dist'))
}
const clear = () => {
    return del(['dist', 'temp'])
}
//开发服务器
//Serve前需要build，否则可能出现dist还没生成的情况，因此serve会用在组合任务里。
const serve = () => {
    //监视变化
    watch('src/assets/styles/*.scss', convertCss)
    watch('src/assets/scripts/*.js', convertJs)
    watch('src/**/*.html', convertHtml)
    watch([
        'src/assets/images/**',
        'src/assets/fonts/**',
        'public/**'
    ], browserSync.reload)
    browserSync.init({
        //开发服务器基础代码
        notify: false,
        port: 3090,
        open: true,
        //dist(划掉)temp下修改后即更新
        files: 'temp/**',
        server: {
            //baseDir的作用是指定网站根目录，加工后的是dist
            //指定为数组会依序查找。在这里是为了开发阶段无需转换部分类型，未经转换的文件将从第二、第三序路径内查找
            baseDir: ['temp', 'src', 'public'],
            //routes处理诸如项目根目录下，dist之外的文件，优先于baseDir去查找
            routes: {
                '/node_modules': 'node_modules'
            }
        }
    })
}
//文件引用处理、文件压缩
const convertUseref = () => {
    return src('temp/**/*.html', { base: 'temp' })
        //searchPath指定dist和根目录，分别处理发布和node_modules等路径
        .pipe(plugins.useref({ searchPath: ['temp', '.'] }))
        //用if条件分类压缩
        .pipe(plugins.if(/\.js$/, plugins.uglify()))
        .pipe(plugins.if(/\.css$/, plugins.cleanCss()))
        .pipe(plugins.if(/\.html$/, plugins.htmlmin({
            collapseWhitespace: true,
            minifyCSS: true,
            minifyJS: true
        })))
        .pipe(dest('dist'))
}
//重新规划构建过程
//将temp和dist划分开发布前后的操作

const compile = parallel(convertCss, convertJs, convertHtml)
const build = series(clear, parallel(series(compile, convertUseref), convertImage, convertFont, convertExtra
))
const develop = series(compile, serve)

module.exports = {
    clear,
    compile,
    build,
    develop
}